The Chicago Board of Ethics requires that all lobbyists engaging with City officials register with the Board and file regular activity reports. The activity reports are filed electronically and include compensation paid to lobbyists by clients (the organizations and firms that hire lobbyists), lobbyist contributions to public and elected City officials, and lobbying activities (meetings with government departments or officials) conducted on behalf of clients.
The recent controversy surrounding unregistered lobbying by individuals contacting Mayor Rahm Emmanuel through his personal email account (see here, here, and here), suggests that there is additional unregistered lobbying activity happening in Chicago. This analysis necessarily focuses only on registered activity reported to the City and made electronically available on the City of Chicago’s Open Data Portal.
# Graph activity
activity %>%
filter(PERIOD_START < as.Date('2019-01-01')) %>%
mutate(year = format(PERIOD_START, '%Y'),
PERIOD_START = as.yearqtr(PERIOD_START, format = "%Y-%m-%d")) %>%
group_by(year, ACTION) %>%
summarise(n = n()) %>%
ggplot(aes(year, n)) +
geom_line(aes(group=ACTION, color=ACTION), size = 1) +
scale_color_manual(values = as.vector(dark_colors[c('blue', 'purple', 'red')])) +
scale_y_continuous(label=comma) +
annotate('text', x=5.2, y=14500, label = "There has been 80% growth in the total \nnumber of lobbying actions since 2012, \nlargely driven by 95% growth in \nAdministrative actions since 2016",
size = 3) +
labs(title="Lobbying activity has shifted toward Administrative \nactions since 2016",
subtitle="Annual Lobbying Actions by Type, 2012 - 2018",
caption="Source: City of Chicago Lobbyist Data, Activity",
x = "Years",
y = "Number of Lobbying Actions") +
theme_claire +
theme(legend.position = c(0.15, 0.8))
Lobbying is a commonplace activity at all levels of government. In Chicago, lobbying “Actions” are divided into three categories: Administrative, Legislative, and Both. Administrative actions are meant to spur administrative action, including meetings regarding contract implementation, marketing services to City agencies, or submitting information regarding redevelopment plans. Legislative actions are intended to encourage support or opposition for specific ordinances or bills before the City legislature. The “Both” category includes some combination of the two. There is a notable increase in the number of Administrative actions beginning in 2016 and continuing to the present. This trend warrants further exploration.
# Separate all words in the Action Sought field
word_summary <- activity %>%
filter(PERIOD_START < as.Date('2019-01-01')) %>%
mutate(ACTION_SOUGHT_WORDS = as.vector(str_split(ACTION_SOUGHT, pattern = c(" ", ", ")))) %>%
summarise(WORDS = paste(ACTION_SOUGHT, collapse = ", ")) %>%
mutate(WORDS_SEP = as.vector(str_split(WORDS, pattern = "[^a-zA-Z0-9]? ")))
# Define set of filler words to exclude
common_words <- c("A", "AND", "AT", "OF", "IN", "THE", "BE", "TO", "THAT", "HAVE",
"IT", "/", "&", "FOR", "N", "E", "W", "S", "L", "WITH", "ON")
# Count frequency of each word
word_counts <- data.frame(table(word_summary$WORDS_SEP[1])) %>%
rename(WORD = Var1, COUNT = Freq) %>%
filter(!(WORD %in% common_words)) %>%
arrange(desc(COUNT)) %>%
slice(1:50)
# Plot
word_counts %>%
ggplot(aes(size = COUNT, label = WORD, color = COUNT)) +
geom_text_wordcloud() +
scale_size(range = c(2, 8), guide = FALSE) +
scale_color_continuous(low = light_colors['blue'], high = dark_colors['blue']) +
scale_y_continuous(breaks = NULL) +
scale_x_continuous(breaks = NULL) +
labs(x = '', y = '') +
labs(title="Real estate-related issues are the most frequently discussed items \nin lobbying meetings",
subtitle="Most Freqently Used Words in Activity Descriptions, 2012-2018",
caption="Source: City of Chicago Lobbyist Data, Activity") +
theme_claire +
theme(panel.background = element_blank(),
panel.border = element_rect(color="black",size=1, fill=NA),
strip.background = element_rect(color="black",size=0.5),
legend.position = "none")
Chicago is currently in the midst of a construction boom. It makes sense, then, that the most frequently used words in the descriptions of lobbying activity include real estate and construction related words like “zoning”, “development”, and “approval”. This suggests that this is the most commonly discussed topic in lobbying meetings.
# Top 20 flag
top_20 <- compensation %>%
filter(PERIOD_START < as.Date('2019-01-01')) %>%
group_by(CLIENT_NAME) %>%
summarise(sum = sum(COMPENSATION_AMOUNT), cnt = n()) %>%
arrange(desc(sum)) %>%
slice(1:20) %>%
select(CLIENT_NAME)
# Add flag to compensation df
compensation %<>% mutate(TOP20 = ifelse(CLIENT_NAME %in% top_20$CLIENT_NAME, "Yes", "No"))
quarters <- c("Q1", "Q2", "Q3", "Q4")
# Plot
c <- compensation %>%
filter(PERIOD_START < as.Date('2019-01-01')) %>%
mutate(year = format(PERIOD_START, '%Y'),
quarter = if_else(format(PERIOD_START, "%m") == "01", "Q1",
if_else(format(PERIOD_START, "%m") == "04", "Q2",
if_else(format(PERIOD_START, "%m") == "07", "Q3",
if_else(format(PERIOD_START, "%m") == "10", "Q4", "MISTAKE"))))) %>%
#quarter = format(PERIOD_START, '%q')) %>%
#PERIOD_START = as.yearqtr(PERIOD_START, format = "%YQ%q")) %>%
group_by(TOP20, quarter, year) %>%
summarise(sum = sum(COMPENSATION_AMOUNT), n = n()) %>%
mutate(sum = sum/1000000) %>%
bind_rows(data_frame(TOP20 = c("No", "Yes"), quarter = c("Q2", "Q2"),
year = c("2012", "2012"), sum = c(0,0), n = c(0,0))) %>%
mutate(sum = if_else(TOP20 == "No" & year == "2012" & quarter == "Q1", sum/2, sum),
sum = if_else(TOP20 == "Yes" & year == "2012" & quarter == "Q1", sum/2, sum),
sum = if_else(TOP20 == "No" & year == "2012" & quarter == "Q2", 9.1936827, sum),
sum = if_else(TOP20 == "Yes" & year == "2012" & quarter == "Q2", 1.8108280, sum)) %>%
ggplot(aes(quarter, sum)) +
geom_col(aes(fill=factor(TOP20, levels=c("No","Yes")))) +
facet_grid(.~ year, space = 'free_x', scales = 'free_x', switch = 'x') +
scale_y_continuous(label=dollar_format()) +
scale_fill_manual(values=c(as.vector(light_colors['blue']), as.vector(dark_colors['blue']))) +
labs(title="The Top 20 Clients Pay ~25% of Lobbyist Compensation",
subtitle="Total Quarterly Lobbyist Compensation, 2012 - 2018",
caption="Source: City of Chicago Lobbyist Data, Compensation",
x = "",
y = "Total Lobbyist Compensation (in Millions)") +
theme_claire +
theme(legend.box = 'horizontal',
legend.position = c(0.46, 0.85),
strip.placement = 'outside',
panel.spacing.x = unit(0,"line")) +
guides(fill=guide_legend(title="Top 20"))
# Define 25% data
points <- compensation %>%
filter(PERIOD_START < as.Date('2019-01-01')) %>%
mutate(year = format(PERIOD_START, '%Y'),
quarter = if_else(format(PERIOD_START, "%m") == "01", "Q1",
if_else(format(PERIOD_START, "%m") == "04", "Q2",
if_else(format(PERIOD_START, "%m") == "07", "Q3",
if_else(format(PERIOD_START, "%m") == "10", "Q4", "MISTAKE"))))) %>%
group_by(year, quarter) %>%
summarise(pct_25 = sum(COMPENSATION_AMOUNT) * .25/1000000, n = n()) %>%
bind_rows(data_frame(year = "2012", quarter = "Q2", pct_25 = 5.50/2, n = 0)) %>%
mutate(pct_25 = if_else(year == "2012" & quarter == "Q1", pct_25/2, pct_25))
# layer 25% point
c + geom_point(data = points,
aes(quarter, pct_25, color = dark_colors['red'])) +
facet_grid(.~ year, space = 'free_x', scales = 'free_x', switch = 'x') +
scale_color_identity(name = "25% Mark",
labels = c(""),
guide = "legend")
Clients pay lobbyists to represent their interests to Chicago government officials. On a quarterly basis, that total amount paid by clients to lobbyists routinely tops $15 Million, indicating the size of the lobbying industry in Chicago. 20 clients out of over 3,000 found in the data routinely constitute about 25% of that total. Further, the total annual amount paid to lobbyists increased 69% between 2012 and 2018, from $36.4M to $61.6M. There is clear seasonality in the total payment amounts that also matches seasonal trends in lobbying activity and lobbyist contributions. It is unclear exactly why this is, but it may be related to the City of Chicago’s budgeting process. A balanced budget must be passed by City Council by December 31 of each year, so individual departments are likely to be making decisions around funding allocations during the first few months of the year.
# Map actual name to target name
keys <- c("ACADEMY FOR URBAN SCHOOL LEADERSHIP", "AIRBNB", "AMERICAN BEVERAGE ASSOCIATION", "ANDELL INC", "PRICEWATERHOUSECOOPERS LLP", "CITIBANK, NA",
"CVS CAREMARK CORP", "DELAWARE NORTH COMPANIES", "DELL", "DOMINION VOTING SYSTEMS INC", "FAMILY GUIDANCE CENTERS INC",
"HILTON WORLDWIDE", "HUDSON GROUP", "JCDECAUX GROUP", "LYFT", "NORESCO LLC", "PRESENCE HEALTH", "SSP AMERICA INC",
"UBER","UNITED PARCEL SERVICE")
values <- c("Academy for Urban School Leadership", "Airbnb", "American Beverage Assc.", "Andell", "PwC", "Citi",
"CVS", "Delaware North", "Dell", "Dominion Voting", "Family Guidance Ctrs",
"Hilton", "Hudson Grp", "JCDecaux Grp", "Lyft", "Noresco", "Presence Health", "SSP America",
"Uber", "UPS")
nick_name <- setNames(as.list(values), keys)
top <- compensation %>%
filter(TOP20 == 'Yes') %>%
group_by(CLIENT_NAME, CLIENT_INDUSTRY) %>%
summarise(sum=sum(COMPENSATION_AMOUNT), n = n()) %>%
mutate(sum = sum/1000000,
INDUSTRY = if_else(CLIENT_INDUSTRY %in% c('HOSPITALITY / RESTAURANT', 'PUBLIC UTILITIES',
'RETAIL', 'EDUCATION', 'RACING & WAGERING', 'TRANSPORTATION'),
'OTHER INDUSTRY', CLIENT_INDUSTRY),
NICK_NAME = nick_name[CLIENT_NAME])
t <-compensation %>%
filter(TOP20 == 'No') %>%
group_by(CLIENT_NAME) %>%
summarise(sum=sum(COMPENSATION_AMOUNT), n = n()) %>%
mutate(sum = sum/1000000) %>%
ggplot() +
geom_point(aes(n, sum), color = light_colors["gray"], size = 2, alpha = 0.4) +
annotate("text", x = 350, y = 2.5, label = "99% of clients paid under\n $2.5M to lobbyists\n in the time period", size = 3)
t + geom_point(data = top, aes(n, sum, color = INDUSTRY), size = 2, alpha = 0.7) +
geom_text_repel(data = top, aes(n, sum, label = NICK_NAME), check_overlap = TRUE, size = 3, hjust = 0, nudge_x = 0.1) +
scale_y_continuous(breaks = seq(0, 10, 2), label=dollar_format(largest_with_cents = 0)) +
scale_color_manual(values = as.vector(dark_colors[1:6])) +
xlim(0, 650) +
labs(title="Tech Companies, Healthcare Providers, and Industry Associations\n are Among the Highest Paying Clients",
subtitle="Compensation Payments to Lobbyists, 2012 - 2018",
caption="Source: City of Chicago Lobbyist Data, Compensation",
x = "Number of Payments",
y = "Total Compensation (in Millions)") +
theme_claire +
theme(legend.text=element_text(size=6),
legend.title=element_text(size=8),
legend.position = c(0.85, 0.2)) +
guides(color=guide_legend(title="Industry of Top 20"))
In contrast to the vast majority of clients, the top 20 clients in terms of compensation paid to lobbyists each paid over $2.5M between 2012 and 2018. While any organization, including non-profits and other public service entities, may lobby government, the top 20 clients are almost all private companies with a national profile. The top spender, the American Beverage Association, has consistently paid lobbyists to advocate to the Mayor and City Council against legislation like the proposed Soda Tax and a ban on high-caffeine energy drinks proposed in 2013. Technology companies including Uber, Lyft, and Dell also rank high on the list.
top20cloud <- activity %>%
mutate(TOP20 = ifelse(CLIENT_NAME %in% top_20$CLIENT_NAME, "Yes", "No")) %>%
filter(PERIOD_START > as.Date('2014-12-31') & TOP20 == "Yes") %>%
mutate(ACTION_SOUGHT_WORDS = as.vector(str_split(ACTION_SOUGHT, pattern = c(" ", ", ")))) %>%
#group_by(ACTION) %>%
summarise(WORDS = paste(ACTION_SOUGHT, collapse = ", ")) %>%
mutate(WORDS_SEP = as.vector(str_split(WORDS, pattern = "[^a-zA-Z0-9]? ")))
common_words <- c("A", "AND", "AT", "OF", "IN", "THE", "BE", "TO", "THAT", "HAVE",
"IT", "/", "&", "FOR", "N", "E", "W", "S", "L", "WITH", "ON")
word_counts_top20 <- data.frame(table(top20cloud$WORDS_SEP[1])) %>%
rename(WORD = Var1, COUNT = Freq) %>%
filter(!(WORD %in% common_words)) %>%
arrange(desc(COUNT)) %>%
slice(1:50)
word_counts_top20 %>%
ggplot(aes(size = COUNT, label = WORD, color = COUNT)) +
geom_text_wordcloud() +
scale_size(range = c(2, 8), guide = FALSE) +
scale_color_continuous(low = light_colors['blue'], high = dark_colors['blue']) +
scale_y_continuous(breaks = NULL) +
scale_x_continuous(breaks = NULL) +
labs(x = '', y = '') +
#facet_grid(rows = vars(ACTION), switch="both") +
labs(title="The top 20 clients are discussing the specific concerns \nof their businesses with city officials",
subtitle="Most Freqently Used Words in Activity Descriptions Among the Top 20 Clients, 2015-2018",
caption="Source: City of Chicago Lobbyist Data, Activity") +
theme_claire +
theme(panel.background = element_blank(),
panel.border = element_rect(color="black",size=1, fill=NA),
strip.background = element_rect(color="black",size=0.5),
legend.position = "none")
When compared to the general wordclound above, it is clear that these words are more specific to the interests of the top 20 clients. There is more discussion of high-level business concerns like regulation. We also see terms relating to the specific businesses of the top 20 clients, like “ridesharing” for Uber and Lyft, and “digital network”, the term describing the network of screens displaying advertisements commonly seen at airports, for the JCDecaux Group.
# try log scale? add annotation,
compensation %>%
filter(TOP20 == 'Yes') %>%
group_by(LOBBYIST_NAME) %>%
summarise(sum = sum(COMPENSATION_AMOUNT), log_sum = log10(sum(COMPENSATION_AMOUNT)), n = n()) %>%
mutate(sum = sum/1000000,
cat = if_else(sum < 1, 'No', 'Yes')) %>%
ggplot(aes(reorder(tools::toTitleCase(tolower(LOBBYIST_NAME)), log_sum), log_sum)) +
geom_point(aes(color = cat), stat = 'identity', size = 3) +
scale_color_manual(values = as.vector(dark_colors[c("blue", "red")])) +
labs(title="The Top 20 Clients Paid 63 Lobbyists Over the Time Period;\n 8 Earned Over $1M Each",
subtitle="Log of Total Compensation to Lobbyists by Top 20 Clients, 2012 - 2018",
caption="Source: City of Chicago Lobbyist Data, Compensation",
x = "Lobbyist",
y = "Log Scale of Total Compensation") +
theme_claire +
theme(axis.text.x = element_text(angle = 90, hjust = 1),
legend.position = c(0.15, 0.75)) +
guides(color=guide_legend(title="Paid Over $1M"))
Between 2012 and 2018, the top 20 clients paid 63 lobbyists to represent their interest, with 8 earning over $1M. David Dring, Courtney Nottage, and Michael Kasper, all employed by the lawfirm Fletcher, O’Brien, Kasper, and Nottage, earned over $15M each. John Kelly, Jr., the president of AllCirco earned $13.7M. Victor Reyes and Amy Kurson are partners at the lawfirm Reyes Kurson and each earned about $1M. Patrick Carey and John Dunn are both partners at the lawfirm McGuire Woods and earned $3.0M and $4.8M, respectively.
# Set threshold for industries to show individually
keep <- compensation %>%
filter(PERIOD_START > as.Date('2014-12-31')) %>%
group_by(CLIENT_INDUSTRY) %>%
summarise(sum = sum(COMPENSATION_AMOUNT)) %>%
arrange(desc(sum)) %>%
mutate(KEEP = if_else(sum > 7000000, 1, 0))
# Set Lawfirm and Industry Lookups for labeling
lobbyist_name <- c("VICTOR REYES", "AMY KURSON", "PATRICK CAREY", "JOHN DUNN", "JOHN KELLY, JR.",
"DAVID DRING", "COURTNEY NOTTAGE", "MICHAEL KASPER")
lawfirm <- c("", "RK", "MW", "MW", "ALLCIRCO",
"FOKN", "FOKN", "FOKN")
law_names <- setNames(as.list(lawfirm), lobbyist_name)
full_industry <- c("REAL ESTATE & CONSTRUCTION", "INFO/TECH PRODUCTS OR SERVICES", "HOSPITALITY / RESTAURANT",
"TRADE & PROFESSIONAL ASSOCIATIONS", "FINANCIAL / BANKING")
short_industry <- c("REAL ESTATE", "TECH", "HOSPITALITY",
"TRADE & PRO ASSCS", "FINANCIAL")
industry_lookup <- setNames(as.list(short_industry), full_industry)
compensation %>%
left_join(keep, by = "CLIENT_INDUSTRY") %>%
mutate(LAWFIRM = if_else(LOBBYIST_NAME %in% names(law_names), as.character(law_names[LOBBYIST_NAME]), "OTHER"),
REAL_ESTATE = if_else(str_detect(CLIENT_INDUSTRY, "REAL ESTATE"), "Yes", "No"),
REAL_ESTATE = if_else(is.na(REAL_ESTATE), "No", REAL_ESTATE),
CLIENT_INDUSTRY = if_else(KEEP == 0, "OTHER", CLIENT_INDUSTRY),
CLIENT_INDUSTRY = if_else(CLIENT_INDUSTRY %in% names(industry_lookup), as.character(industry_lookup[CLIENT_INDUSTRY]), CLIENT_INDUSTRY)) %>%
filter(PERIOD_START > as.Date('2014-12-31') & KEEP == 1) %>%
group_by(CLIENT_INDUSTRY, TOP20, LAWFIRM) %>%
summarise(sum = sum(COMPENSATION_AMOUNT)) %>%
mutate(sum = sum/1000000) %>%
ggplot(aes(y = sum, axis1 = CLIENT_INDUSTRY, axis2 = LAWFIRM)) +
geom_alluvium(aes(fill = TOP20)) +
geom_stratum(width = 1/12, fill = "black", color = "grey") +
geom_label(stat = "stratum", label.strata = TRUE) +
scale_x_discrete(limits = c("Top 20 Clients", "Lawfirms"), expand = c(.05, .05)) +
scale_y_continuous(label=dollar_format()) +
scale_fill_manual(values = as.vector(dark_colors[4:3])) +
labs(title="Top 20 clients provide the majority of the lobbying revenue for the major lawfirms",
subtitle="Compensation Flow Between Industries and Lawfirms, 2015-2018",
caption="Source: City of Chicago Lobbyist Data, Compensation",
y = "Total Compensation (in Millions)") +
theme_claire +
theme(legend.position = c(.95, .85))
The top 20 clients are both a large share of the compensation coming from their respective industries, and a significant proportion of the revenue at the major law firms. Also note that while real estate-related lobbying activities are the most commmon, no real estate developer is among the top 20 clients, nor do they employ any of the major lobbying firms.
council %<>%
mutate(LAST_NAME = str_trim(toupper(str_extract(council$` Person Name`, '^[A-Za-z\']+'))),
LAST_NAME = if_else(str_detect(` Person Name`, 'Moore, D'), 'DAVID MOORE', LAST_NAME),
LAST_NAME = if_else(str_detect(` Person Name`, 'Moore, J'), 'JOE MOORE', LAST_NAME))
alderman_contributions <- contribution %>%
mutate(ALDERMAN = "") %>%
mutate(ALDERMAN = if_else(str_detect(RECIPIENT, 'ARENA'), 'ARENA', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'AUSTIN'), 'AUSTIN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'BEALE'), 'BEALE', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'BROOKINS'), 'BROOKINS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'BURKE'), 'BURKE', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'BURNETT'), 'BURNETT', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'CAPPLEMAN'), 'CAPPLEMAN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'CARDENAS'), 'CARDENAS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'COCHRAN'), 'COCHRAN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'CURTIS'), 'CURTIS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'DOWELL'), 'DOWELL', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'EMANUEL'), 'EMANUEL', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'ERVIN'), 'ERVIN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'FOULKES'), 'FOULKES', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'HAIRSTON'), 'HAIRSTON', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'HARRIS'), 'HARRIS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'HOPKINS'), 'HOPKINS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'KING'), 'KING', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'LAURINO'), 'LAURINO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'LOPEZ'), 'LOPEZ', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'MALDONADO'), 'MALDONADO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'MELL'), 'MELL', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'MITCHELL'), 'MITCHELL', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'MITTS'), 'MITTS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'JOE MOORE'), 'JOE MOORE', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'DAVID MOORE'), 'DAVID MOORE', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'MORENO'), 'MORENO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'MUNOZ'), 'MUNOZ', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'NAPOLITANO'), 'NAPOLITANO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, "O'CONNOR"), "O'CONNOR", ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, "O'SHEA"), "O'SHEA", ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'OSTERMAN'), 'OSTERMAN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'PAWAR'), 'PAWAR', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'QUINN'), 'QUINN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'RAMIREZ'), 'RAMIREZ', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'REBOYRAS'), 'REBOYRAS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'REILLY'), 'REILLY', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SADLOWSKI'), 'SADLOWSKI', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SANTIAGO'), 'SANTIAGO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SAWYER'), 'SAWYER', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SCOTT'), 'SCOTT', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SILVERSTEIN'), 'SILVERSTEIN', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SMITH'), 'SMITH', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SOLIS'), 'SOLIS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'SPOSATO'), 'SPOSATO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'TABARES'), 'TABARES', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'TALIAFERRO'), 'TALIAFERRO', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'THOMPSON'), 'THOMPSON', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'TUNNEY'), 'TUNNEY', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'VALENCIA'), 'VALENCIA', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'VILLEGAS'), 'VILLEGAS', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'WAGUESPACK'), 'WAGUESPACK', ALDERMAN),
ALDERMAN = if_else(str_detect(RECIPIENT, 'ZALEWSKI'), 'ZALEWSKI', ALDERMAN)
) %>%
filter(ALDERMAN != "" & ALDERMAN != "EMANUEL" & ALDERMAN != "VALENCIA")
ald_totals <- alderman_contributions %>%
filter(CONTRIBUTION_DATE > as.Date('2014-12-31')) %>%
group_by(ALDERMAN) %>%
summarise(sum = sum(AMOUNT), n = n()) %>%
arrange(desc(sum))
# Set names for annotations
high_name <- 'BURKE'
high_mid_name <- 'LOPEZ'
mid_name <- 'CAPPLEMAN'
low_mid_name <- 'SADLOWSKI'
low_name <- 'TABARES'
# Set amounts for annotations
high_amt <- '$84k'
high_mid_amt <- '$20k'
mid_amt <- '$14k'
low_mid_amt <- '$5k'
low_amt <- '$0k'
alderman_contributions %>%
filter(CONTRIBUTION_DATE > as.Date('2014-12-31')) %>%
left_join(ald_totals, by = 'ALDERMAN') %>% #glimpse()
#mutate(ALDERMAN = tools::toTitleCase(tolower(ALDERMAN))) %>% glimpse()
ggplot() +
geom_boxplot(aes(reorder(ALDERMAN, sum), AMOUNT), alpha = 0.8) +
coord_flip() +
annotate("text", x = 49.7, y = 1600, label = "Total", size = 3) +
annotate("text", x = high_name, y = 1600, label = high_amt, size = 3) +
annotate("text", x = high_mid_name, y = 1600, label = high_mid_amt, size = 3) +
annotate("text", x = mid_name, y = 1600, label = mid_amt, size = 3) +
annotate("text", x = low_mid_name, y = 1600, label = low_mid_amt, size = 3) +
annotate("text", x = low_name, y = 1600, label = low_amt, size = 3) +
annotate("text", x = 'TABARES', y = 600, label = "Appointed on July 13, 2018 to replace Ald. Zalewski in 23rd Ward", size = 2) +
annotate("text", x = 'ZALEWSKI', y = 700, label = "Resigned from 23rd Ward\n on May 31, 2018", size = 2) +
annotate("rect", xmin = high_mid_name, xmax = 50, ymin = 0, ymax = 1550, fill = light_colors["orange"], alpha = .2) +
annotate("rect", xmin = mid_name, xmax = high_mid_name, ymin = 0, ymax = 1550, fill = light_colors["green"], alpha = .2) +
annotate("rect", xmin = low_mid_name, xmax = mid_name, ymin = 0, ymax = 1550, fill = light_colors["purple"], alpha = .2) +
annotate("rect", xmin = 0, xmax = low_mid_name, ymin = 0, ymax = 1550, fill = light_colors["blue"], alpha = .2) +
annotate("text", x = 49.5, y = 200, label = "Charged with attempted extortion on Jan 3, 2019", size = 2, fontface = 2) +
scale_y_continuous(label=dollar_format()) +
labs(title="Since the 2015 Municipal Election, Lobbyists Have Contributed\n Significant Amounts to Aldermen",
subtitle="Distribution of Lobbyist Contributions to Aldermen Ordered by Total, 2015 - 2018",
caption="Source: City of Chicago Lobbyist Data, Contributions",
x = "Alderman (ordered by total lobbyist contributions)",
y = "Contribution Amount") +
theme_claire
Virtually all elected members of the City Council received contributions from lobbyists since the last municipal election; the only exception is Ald. Tabares who was appointed to on July 13, 2018. There is huge variation in the total contributions from lobbyists since the last municipal election. For example, Ald. Reilly of the 42nd Ward (incl. River North, Gold Cost, and Streeterville), first elected in 2007 and Vice Mayor since 2015, received over $600k while Ald. Mitchell, a first term alderman from the 7th Ward (incl. South Shore, South Chicago, and Calumet Heights) received under $1k. Ald. Ed Burke was the Finance Committee Chairman and received the highest total contributions before being indicted for attempted extortion on January 3, 2019. Note that campaign contributions by registered lobbyists are limited to $1,500 per candidate per calendar year by the Chicago Govermental Ethics Ordinance.
options(tigris_class = "sf")
water <- area_water("17", "031")
roads <- roads(year = 2016, "17", "031") %>% filter(RTTYP %in% c("I", "S"))
contrib_levels <- c(NA, '$0 - $4,999', '$5,000 - $9,999', '$10,000 - $19,999', '$20,000 - $39,999', '$40,000')
addNA(contrib_levels)
ward_name <- wards %>%
left_join(council %>% select(`Ward/Office`, LAST_NAME), by = c("ward" = "Ward/Office"))
ward_name %>% #glimpse() %>%
left_join(ald_totals, by = c("LAST_NAME" = "ALDERMAN")) %>%
#filter(is.na(sum)) %>%
mutate(Total = if_else(sum < 5000, '$0 - $4,999',
if_else(sum >= 5000 & sum < 10000, '$5,000 - $9,999',
if_else(sum >= 10000 & sum < 20000, '$10,000 - $19,999',
if_else(sum >= 20000 & sum < 40000, '$20,000 - $39,999',
if_else(sum >= 40000, '$40,000', 'OTHER'))))),
Total = factor(Total, levels = contrib_levels),
lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
lat = map_dbl(geometry, ~st_centroid(.x)[[2]])
) %>%
ggplot() +
geom_sf(aes(fill = Total), size = 0.1) +
geom_sf(data = water, colour = "#eef7fa", size = .1,fill = "#e6f3f7") +
geom_sf(data = roads, size = .2, colour = dark_colors[['gray']]) +
geom_text(aes(x = lon, y = lat, label = ward), size = 3) +
labs(title="Lobbyist contributions to alderman mirror braoder investment trends",
subtitle="Total Lobbyist Contributions to Alderman by Ward, 2015-2018",
caption="Source: City of Chicago Lobbyist Data, Contributions",
x = "",
y = "") +
scale_fill_manual(values = c('#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'),
na.value = light_colors[['gray']]) +
coord_sf(xlim = c(-87.95, -87.5) , ylim = c(41.65, 42.02))+
theme_claire +
theme(panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank())
There appears to be some geographic concentration of contributions by lobbyists to alderman that mirrors patterns of investment in the city as a whole, with North Side alderman receiving larger contributions that those in the South and West sides. Since real estate development is a major driver of lobbying activity, this may be related to influence that aldermen have over zoning and development in their wards: lobbyists representing real estate clients may contribute more to aldermen who represent profitable areas for development. A notable exception to the geographic trend is Ward 14, which was represented by Ald. Burke before his indictment in January.
building_permits_sf <- building_permits %>%
filter(!is.na(lat) & ISSUE_DATE > as.Date('2014-12-31') & ISSUE_DATE < as.Date('2019-01-01')) %>%
mutate(year = format(ISSUE_DATE, '%Y')) %>%
st_as_sf(coords = c("lon", "lat"),
crs = 4326, agr = "constant")
re_comp <- compensation %>% filter(str_detect(CLIENT_INDUSTRY, 'REAL ESTATE'))
#compensation %>% filter(COMPEN)
#re_comp %>% group_by(LOBBYIST_NAME) %>% summarise(sum = sum(COMPENSATION_AMOUNT)) %>% arrange(desc(sum))
ald_re_totals <- alderman_contributions %>%
filter(CONTRIBUTION_DATE > as.Date('2014-12-31')) %>%
mutate(paid_re = if_else(LOBBYIST_NAME %in% unique(re_comp$LOBBYIST_NAME), 'Yes', 'No')) %>%
filter(paid_re == 'Yes') %>%
group_by(ALDERMAN) %>%
summarise(sum = sum(AMOUNT)) %>% arrange(desc(sum))
#dev_ratio <- ward_name %>% #glimpse() %>%
# left_join(ald_re_totals, by = c("LAST_NAME" = "ALDERMAN")) %>%
# st_set_crs(4326) %>%
# st_join(building_permits_sf %>% select(ISSUE_DATE, ESTIMATED_COST, FULL_ADDRESS, geometry),
# join = st_intersects, left = TRUE) %>%
# group_by(ward, sum) %>%
# summarise(total_costs = sum(ESTIMATED_COST), n = n()) %>%
# mutate(dollars_per_dev = sum/n, contrib_by_cost = sum/total_costs, cost_by_contrib = total_costs/sum)
ratio_levels <- c(NA, '< 20%', '20% - 40%', '40% - 60%', '60% - 80%', '80%+')
#c(NA, '< $20', '$20 - $49', '$50 - $99', '$100 - $499', '$500+')
addNA(ratio_levels)
## [1] <NA> < 20% 20% - 40% 40% - 60% 60% - 80% 80%+
## Levels: < 20% 20% - 40% 40% - 60% 60% - 80% 80%+ <NA>
#dev_ratio %>%
# mutate(ratio = if_else(cost_by_contrib < 6000, '< $6,000',
# if_else(cost_by_contrib >= 5000 & cost_by_contrib < 20000, '$5,000 - $20,000',
# if_else(cost_by_contrib >= 20000 & cost_by_contrib < 50000, '$20,000 - $49,999',
# if_else(cost_by_contrib >= 50000 & cost_by_contrib < 100000, '$50,000 - $99,999',
# if_else(cost_by_contrib >= 100000, '$100,000+', 'OTHER'))))),
# ratio = factor(ratio, levels = ratio_levels),
# lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
# lat = map_dbl(geometry, ~st_centroid(.x)[[2]])) %>%
# ggplot() +
# geom_sf(aes(fill = ratio), size = 0.1) +
# geom_sf(data = water, colour = "#eef7fa", size = .1,fill = "#e6f3f7") +
# geom_sf(data = roads, size = .2, colour = dark_colors[['gray']]) +
# geom_text(aes(x = lon, y = lat, label = ward), size = 3) +
# labs(title="Lobbyist contributions to alderman mirror braoder investment trends",
# subtitle="Map of Total Contributions to Alderman by Ward, 2015-2018",
# caption="Source: City of Chicago Lobbyist Data, Contributions",
# x = "",
# y = "") +
# scale_fill_manual(values = c('#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'),
# na.value = light_colors[['gray']]) +
# coord_sf(xlim = c(-87.95, -87.5) , ylim = c(41.65, 42.02))+
# theme_claire +
# theme(panel.grid.major.x = element_blank(),
# panel.grid.major.y = element_blank())
#dev_ratio %>% arrange(desc(cost_by_contrib))
ald_re_ratio <-
ald_re_totals %>%
left_join(ald_totals, by = 'ALDERMAN') %>%
mutate(re_ratio = sum.x/sum.y) %>%
arrange(desc(re_ratio))
ward_name %>%
left_join(ald_re_ratio, by = c("LAST_NAME" = "ALDERMAN")) %>%
mutate(proportion = if_else(re_ratio < 0.2, '< 20%',
if_else(re_ratio >= 0.2 & re_ratio < 0.4, '20% - 40%',
if_else(re_ratio >= 0.4 & re_ratio < 0.6, '40% - 60%',
if_else(re_ratio >= 0.6 & re_ratio < 0.8, '60% - 80%',
if_else(re_ratio >= 0.8, '80%+', 'OTHER'))))),
ratio = factor(proportion, levels = ratio_levels),
lon = map_dbl(geometry, ~st_centroid(.x)[[1]]),
lat = map_dbl(geometry, ~st_centroid(.x)[[2]])) %>%
ggplot() +
geom_sf(aes(fill = proportion), size = 0.1) +
geom_sf(data = water, colour = "#eef7fa", size = .1,fill = "#e6f3f7") +
geom_sf(data = roads, size = .2, colour = dark_colors[['gray']]) +
geom_text(aes(x = lon, y = lat, label = ward), size = 3) +
labs(title="Wards with a higher share of real estate contributions \nmay be more influenced by the real estate industry",
subtitle="% Real Estate Lobbyist Contributions to Alderman by Ward, 2015-2018",
caption="Source: City of Chicago Lobbyist Data, Contributions",
x = "",
y = "") +
scale_fill_manual(values = c('#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'),
na.value = light_colors[['gray']]) +# = c('#eff3ff', '#bdd7e7', '#6baed6', '#3182bd', '#08519c'),
#na.value = light_colors[['gray']]) +
coord_sf(xlim = c(-87.95, -87.5) , ylim = c(41.65, 42.02))+
theme_claire +
theme(panel.grid.major.x = element_blank(),
panel.grid.major.y = element_blank()) +
guides(fill=guide_legend(title="% Contributions for Real Estate"))
#ald_re_ratio
The proportion of lobbyist contributions to aldermen that comes from lobbyists that commonly represent real estate projects varies widely by geography. Those that receive a high proportion of contributions from real estate lobbyists may be more subject to influence from real estate developments, though some alderman with a greater diversity of contribution may have higher dollar amounts coming from real estate lobbyists.
# shows more about who is and who isn't
# Bin lobbyists by location? octant of community areas
# sankey diagram
paid_by_top20 <- compensation %>%
filter(TOP20 == 'Yes') %>%
group_by(LOBBYIST_NAME) %>%
summarise(sum = sum(COMPENSATION_AMOUNT), n = n()) %>%
filter(sum >= 1000000)
alderman_contributions %>%
mutate(paid_top20 = if_else(LOBBYIST_NAME %in% paid_by_top20$LOBBYIST_NAME | LOBBYIST_NAME == 'REYES KURSON', TRUE, FALSE))%>%
filter(CONTRIBUTION_DATE > as.Date('2014-12-31') & paid_top20) %>%
left_join(ald_totals, by = 'ALDERMAN') %>%
group_by(ALDERMAN, LOBBYIST_NAME) %>%
summarise(sum = sum(AMOUNT), n = n()) %>%
ggplot() +
geom_tile(aes(reorder(LOBBYIST_NAME, sum), reorder(ALDERMAN, sum), fill = sum), color = 'black') +
scale_fill_gradient(low = light_colors['blue'], high = dark_colors['blue'], label=dollar_format()) +
labs(title="The Highest Paid Lobbyists by the Top 20 Clients Make\n Contributions to Almost Every Alderman",
subtitle="Total Contributions by Top Paid Lobbyists, 2015-2018",
caption="Source: City of Chicago Lobbyist Data, Contributions",
x = "Lobbyist",
y = "Alderman (ordered by total contributions from included lobbyists)") +
theme_claire +
theme(axis.text.x = element_text(angle = 90, hjust = 1),
panel.grid = element_blank()) +
guides(fill=guide_legend(title="Total Payments"))
The lobbyists paid the most compensation by the top 20 firms appear to have a strategy of blanket, moderate, financial support for almost all aldermen. One notable exception is John Kelly, President and Owner of the public affairs consulting firm All-Circo, Inc, who appears to concentrate on only a few. Two of the eight attorneys paid over $1M, Amy Kurson and Victor Reyes, are both partners at the lawfirm Reyes Kurson. Their contribution data was not included in the data protal contribution records, so aggregate records from the firm were added from IllinoisSunshine.com.